package CreationPattern.Singleton;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @Classname : SingletonVulnerabilitiesClient
 * @Description : 测试 单例模式漏洞修复
 * @Author : chentianyu
 * @Date 2022/12/26 23:20
 */


public class SingletonVulnerabilitiesClient {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        System.out.println("正常方式获取单例对象");
        Vulnerabilities s1 = Vulnerabilities.getInstance();
        Vulnerabilities s2 = Vulnerabilities.getInstance();
        System.out.println(s1);
        System.out.println(s2);
        System.out.println("--------------------------------------------------------------------");


        System.out.println("通过反序列化的方式构造多个对象");
        // 序列化
        FileOutputStream fos = new FileOutputStream("src/main/resources/a.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(s1);
        oos.close();
        fos.close();
        // 反序列化
        FileInputStream fis = new FileInputStream("src/main/resources/a.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Vulnerabilities s3 = (Vulnerabilities) ois.readObject();
        System.out.println(s3);
        System.out.println("--------------------------------------------------------------------");


        System.out.println("通过反射的方式直接调用私有构造器");
        Class<Vulnerabilities> clazz = (Class<Vulnerabilities>)Class.forName("CreationPattern.Singleton.Vulnerabilities");
        Constructor<Vulnerabilities> cons = clazz.getDeclaredConstructor();
        cons.setAccessible(true);
        Vulnerabilities s4 = cons.newInstance();
        Vulnerabilities s5 = cons.newInstance();
        System.out.println(s4);
        System.out.println(s5);
        System.out.println("--------------------------------------------------------------------");

    }
}


/** 2022/12/26
 * 正常方式获取单例对象
 * CreationPattern.Singleton.Vulnerabilities@75b84c92
 * CreationPattern.Singleton.Vulnerabilities@75b84c92
 * --------------------------------------------------------------------
 * 通过反序列化的方式构造多个对象
 * CreationPattern.Singleton.Vulnerabilities@75b84c92
 * --------------------------------------------------------------------
 * 通过反射的方式直接调用私有构造器
 * Exception in thread "main" java.lang.reflect.InvocationTargetException
 * 	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 * 	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 * 	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 * 	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 * 	at CreationPattern.Singleton.SingletonClient02.main(SingletonClient02.java:45)
 * Caused by: java.lang.RuntimeException: 警告，正在尝试通过反射的方式直接调用私有构造器！
 * 	at CreationPattern.Singleton.Vulnerabilities.<init>(Vulnerabilities.java:20)
 * 	... 5 more
 */